home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Commun⁄Network / RevRdist Folder / RevRdist / RevRdist src / simpledialog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-12  |  11.1 KB  |  386 lines  |  [TEXT/KAHL]

  1. /*
  2.     Present a dialog box with a text rectangle, a scroll bar, and an OK
  3.     button.  This can be used as a help dialog.  Pass in a dialog
  4.     resource number and a handle to the text.  The dialog should
  5.     have the OK button as the first item, and user items for the
  6.     second and third items.  The second is the rect in which the
  7.     control is drawn, the third is the rect in which text is drawn.
  8.     Only the OK button should be enabled.
  9.  
  10.     The text handle should be locked before calling TextDlog and
  11.     unlocked after.
  12.  
  13.     Original author:                    dubois@uwmacc.UUCP (Paul DuBois)
  14.     with a few changes & cleanup by:    blob@apple.com  (Brian Bechtel)
  15. */
  16.  
  17. #include   <Events.h>
  18. #include   <Dialogs.h>
  19. #include   <Controls.h>
  20.  
  21. #define ETX 03      /* Enter key */
  22. #define CR  13      /* Return key */
  23.  
  24. enum        /* item numbers */
  25. {
  26.     OKButton = 1,
  27.     scrollBarUser,
  28.     textRectUser
  29. };
  30.  
  31. static ControlHandle    theScroll;
  32. static Boolean          needScroll; /* true if need scroll bar */
  33. static int              curLine;
  34. static int              halfPage;
  35. static TEHandle         teHand;
  36.  
  37. static void HighLightDefault(DialogPtr dPtr);
  38. static pascal void DrawScroll (DialogPtr theDialog, int itemNo);
  39. static pascal void DrawTextRect (DialogPtr theDialog, int itemNo);
  40. static void DoScroll (int lDelta);
  41. static pascal void __TrackScroll (ControlHandle theScroll, int partCode);
  42. static pascal Boolean TextFilter (DialogPtr theDialog,
  43.                     EventRecord *theEvent, int *itemHit);
  44. void TextDialog (int dlogNum,Handle textHandle,int fontNum,int fontSize,
  45.                     Boolean wrap);
  46.  
  47.  
  48.  
  49. /************************************************************************
  50.  *
  51.  *  Function:       HighLightDefault
  52.  *
  53.  *  Purpose:        highlight the default button in a dialog
  54.  *
  55.  *  Returns:        nothing
  56.  *
  57.  *  Side Effects:   standard box is drawn around highlight box
  58.  *
  59.  *  Description:    draws the heavy rounded box around the OK button,
  60.  *                  so that the user knows that hitting enter or return
  61.  *                  is the same as pressing the OK button.
  62.  *
  63.  ************************************************************************/
  64. static void
  65. HighLightDefault(dPtr)
  66. DialogPtr dPtr;
  67. {
  68.     short unusedItemType;
  69.     Handle unusedItemHandle;
  70.     Rect box;
  71.     PenState p;
  72.  
  73.     /*  This next little piece of code puts the default heavy rounded
  74.         box around the "OK" button, so the user knows that pressing
  75.         return is the same as hitting "OK"
  76.     */
  77.     SetPort(dPtr);      /* without this, can't highlite OK */
  78.     GetDItem(dPtr, OKButton, &unusedItemType, &unusedItemHandle, &box);
  79.     GetPenState(&p);
  80.     PenSize(3,3);
  81.     InsetRect(&box, -4, -4);
  82.     FrameRoundRect(&box, 16, 16);
  83.     PenSize(p.pnSize.h, p.pnSize.v);
  84. }
  85.  
  86. /************************************************************************
  87.  *
  88.  *  Function:       DrawScroll
  89.  *
  90.  *  Purpose:        draw scroll bar user item
  91.  *
  92.  *  Returns:        nothing
  93.  *
  94.  *  Side Effects:   draws scroll bar user item
  95.  *
  96.  *  Description:    if we need to scroll, show the control.
  97.  *
  98.  ************************************************************************/
  99. static pascal void DrawScroll (theDialog, itemNo)
  100. DialogPtr   theDialog;
  101. int         itemNo;
  102. {
  103.     if (needScroll)
  104.         ShowControl (theScroll);
  105. }
  106.  
  107.  
  108. /*
  109.     Proc for drawing text display user item.
  110. */
  111.  
  112.  
  113. /************************************************************************
  114.  *
  115.  *  Function:       DrawTextRect
  116.  *
  117.  *  Purpose:        draw text display user item
  118.  *
  119.  *  Returns:        nothing
  120.  *
  121.  *  Side Effects:   shows the text
  122.  *
  123.  *  Description:    Get the rectangle for our text.  If we need to scroll,
  124.  *                  frame the rectangle so that it will look correct.
  125.  *                  Get the view rectangle of our text rectangle, and do
  126.  *                  a TEUpdate so that text edit will properly handle
  127.  *                  updating the rectangle.
  128.  *
  129.  ************************************************************************/
  130. static pascal void DrawTextRect (theDialog, itemNo)
  131. DialogPtr   theDialog;
  132. int         itemNo;
  133. {
  134. Rect    r;
  135. short    itemType;
  136. Handle  itemHandle;
  137.  
  138.     GetDItem (theDialog, textRectUser, &itemType, &itemHandle, &r);
  139.     if (needScroll)
  140.         FrameRect (&r);
  141.     r = (**teHand).viewRect;
  142.     TEUpdate (&r, teHand);
  143. }
  144.  
  145.  
  146. /************************************************************************
  147.  *
  148.  *  Function:       DoScroll
  149.  *
  150.  *  Purpose:        scroll to correct position
  151.  *
  152.  *  Returns:        nothing.
  153.  *
  154.  *  Side Effects:   text is scrolled to new position
  155.  *
  156.  *  Description:
  157.  *                  Scroll to the correct position.  lDelta is the
  158.  *                  amount to CHANGE the current scroll setting by.
  159.  *
  160.  ************************************************************************/
  161. static void
  162. DoScroll (lDelta)
  163. int     lDelta;
  164. {
  165. int newLine;
  166.  
  167.     newLine = curLine + lDelta;
  168.     if (newLine < 0) newLine = 0;
  169.     if (newLine > GetCtlMax (theScroll)) newLine = GetCtlMax (theScroll);
  170.     SetCtlValue (theScroll, newLine);
  171.     lDelta = (curLine - newLine ) * (**teHand).lineHeight;
  172.     TEScroll (0, lDelta, teHand);
  173.     curLine = newLine;
  174. }
  175.  
  176.  
  177.  
  178. /************************************************************************
  179.  *
  180.  *  Function:       __TrackScroll
  181.  *
  182.  *  Purpose:        track the scrolling
  183.  *
  184.  *  Returns:        nothing
  185.  *
  186.  *  Side Effects:   scrolling
  187.  *
  188.  *  Description:    get the control part that we're in.  If we're still
  189.  *                  in the same part, we're going to scroll.  Check what
  190.  *                  kind of part we're in, and set our delta accordingly.
  191.  *                  Call DoScroll to actually handle the scrolling.
  192.  *
  193.  ************************************************************************/
  194. static pascal void __TrackScroll (theScroll, partCode)
  195. ControlHandle   theScroll;
  196. int             partCode;
  197. {
  198. int lDelta;
  199.  
  200.     if (partCode == GetCRefCon (theScroll)) /* still in same part? */
  201.     {
  202.         switch (partCode)
  203.         {
  204.             case inUpButton: lDelta = -1; break;
  205.             case inDownButton: lDelta = 1; break;
  206.             case inPageUp: lDelta = -halfPage; break;
  207.             case inPageDown: lDelta = halfPage; break;
  208.         }
  209.         DoScroll (lDelta);
  210.     }
  211. }
  212.  
  213.  
  214. /*
  215.     Filter to handle hits in scroll bar
  216. */
  217.  
  218.  
  219. /************************************************************************
  220.  *
  221.  *  Function:       TextFilter
  222.  *
  223.  *  Purpose:        filter to handle hits in scroll bar
  224.  *
  225.  *  Returns:        false (indicating we should continue within our
  226.  *                  modal dialog)
  227.  *
  228.  *  Side Effects:   May scroll the text
  229.  *
  230.  *  Description:    We're being called as part of a ModalDialog call.
  231.  *                  Check what kind of event activated us.  If it was a
  232.  *                  mouseDown, handle it.  If we were in the thumb, track
  233.  *                  the thumb, otherwise scroll the indicated amount.
  234.  *
  235.  ************************************************************************/
  236. static pascal Boolean TextFilter (theDialog, theEvent, itemHit)
  237. DialogPtr   theDialog;
  238. EventRecord *theEvent;
  239. int         *itemHit;
  240. {
  241. Point   thePoint;
  242. int     thePart;
  243. Boolean result;
  244.  
  245.     result = false;
  246.     switch (theEvent->what)
  247.     {
  248.         case mouseDown:
  249.             thePoint = theEvent->where;
  250.             GlobalToLocal (&thePoint);
  251.             thePart = TestControl (theScroll, thePoint);
  252.             if (thePart == inThumb)
  253.             {
  254.                 (void) TrackControl (theScroll, thePoint, nil);
  255.                 DoScroll (GetCtlValue (theScroll) - curLine);
  256.             }
  257.             else if (thePart != 0)
  258.             {
  259.                 SetCRefCon (theScroll, (long) thePart);
  260.                 (void) TrackControl (theScroll, thePoint, __TrackScroll);
  261.             }
  262.             break;
  263.         case keyDown:
  264.             if ((theEvent->message & charCodeMask) == ETX)
  265.             {
  266.                 *itemHit = 1;
  267.                 result = true;
  268.             }
  269.             if ((theEvent->message & charCodeMask) == CR)
  270.             {
  271.                 *itemHit = 1;
  272.                 result = true;
  273.             }
  274.             break;
  275.         case updateEvt:
  276.         case activateEvt:
  277.             HighLightDefault(theDialog);
  278.             break;
  279.     }
  280.     return (result);
  281. }
  282.  
  283.  
  284.  
  285. /************************************************************************
  286.  *
  287.  *  Function:       TextDialog
  288.  *
  289.  *  Purpose:        put up text dialog with optional scroll bar
  290.  *
  291.  *  Returns:        nothing
  292.  *
  293.  *  Side Effects:   none
  294.  *
  295.  *  Description:    Pass in a dialog number, a handle to the text to
  296.  *                  display, a font number, font size, and a boolean
  297.  *                  indicating whether you want the text to wrap or not.
  298.  *
  299.  *                  The dialog referenced by dlogNum should have the
  300.  *                  OK button as the first item, and user items for the
  301.  *                  second and third items.  The second is the rect in
  302.  *                  which the control is drawn, the third is the rect in
  303.  *                  which text is drawn. Only the OK button should be
  304.  *                  enabled.
  305.  *
  306.  *                  The text handle should be locked before calling us,
  307.  *                  and unlocked afterwards.
  308.  *
  309.  *                  Of course, the font number and size should exist in
  310.  *                  the current system, or it will default to something
  311.  *                  ugly.
  312.  *
  313.  ************************************************************************/
  314. void
  315. TextDialog (dlogNum, textHandle, fontNum, fontSize, wrap)
  316. int     dlogNum;
  317. Handle  textHandle;
  318. int     fontNum;
  319. int     fontSize;
  320. Boolean wrap;
  321. {
  322. GrafPtr        oldPort;
  323. DialogPtr    theDialog;
  324. short        itemNo;
  325. short        itemType;
  326. Handle        itemHandle;
  327. Rect        r;
  328. int            scrollLines;
  329. int            viewLines;
  330. Handle        oldHText;
  331. ProcPtr        filterProc = nil;
  332.  
  333.     GetPort (&oldPort);
  334.     theDialog = GetNewDialog (dlogNum, nil, (WindowPtr)-1L);
  335.     if (!theDialog)
  336.         return;
  337.  
  338.     GetDItem (theDialog, textRectUser, &itemType, &itemHandle, &r);
  339.     SetDItem (theDialog, textRectUser, itemType, (Handle)DrawTextRect, &r);
  340. /*
  341.     incorporate text into a TERec.
  342. */
  343.     SetPort (theDialog);
  344.     TextFont (fontNum);
  345.     TextSize (fontSize);
  346.  
  347.     InsetRect (&r, 4, 4);
  348.     teHand = TENew (&r, &r);
  349.     if (!wrap)
  350.         (**teHand).crOnly = -1;
  351.     oldHText = (**teHand).hText;        /* save this.  restore later */
  352.     (**teHand).hText = textHandle;
  353.     TECalText (teHand);
  354.     viewLines = (r.bottom - r.top) / (**teHand).lineHeight;
  355.     scrollLines = (**teHand).nLines - viewLines;
  356.     needScroll = (scrollLines > 0);
  357.     GetDItem (theDialog, scrollBarUser, &itemType, &itemHandle, &r);
  358.     SetDItem (theDialog, scrollBarUser, itemType, (Handle)DrawScroll, &r);
  359.     if (needScroll)
  360.     {
  361.         theScroll = NewControl (theDialog, &r, "\p", false, 0, 0, 0,
  362.                         scrollBarProc, 0L);
  363.         SetCtlMax (theScroll, scrollLines);
  364.         halfPage = viewLines / 2;
  365.         curLine = 0;
  366.         filterProc = (ProcPtr) TextFilter;
  367.     }
  368.  
  369.     ShowWindow (theDialog);
  370.     HighLightDefault (theDialog);
  371.  
  372.     do {
  373.         ModalDialog (filterProc, &itemNo);
  374.     } while (itemNo != OKButton);
  375.  
  376. /*
  377.     restore hText field of TE record before disposing of it.
  378. */
  379.     (**teHand).hText = oldHText;
  380.     TEDispose (teHand);
  381.  
  382.     if (needScroll)
  383.         DisposeControl (theScroll);
  384.     SetPort (oldPort);
  385.     DisposDialog(theDialog);
  386. }